#include "array.h"
#include "sparse.h"

svector::svector(int l, const Array<int>& ai, const Array<real>& av) {
    int i;
    len = av.size();
    buf = new svector::entry[len];
    for (i = 0; i < len; i++) {
        buf[i].ind = ai[i];
        buf[i].val = av[i];
    }
    label = l;
}

svector::svector() {
    label = 0;
    buf = 0;
    len = 0;
    norm = -1;
}

svector::svector(const svector& v): buf(new svector::entry[v.len]), len(v.len) {
    for (int i = 0; i < len; i++)
        buf[i] = v.buf[i];
}

svector& svector::operator=(const svector& v) {
    if (this == &v)
        return *this;
    delete[]buf;
    len = v.len;
    buf = new svector::entry[len];
    for (int i = 0; i < len; i++)
        buf[i] = v.buf[i];
    return *this;
}

svector::~svector() {
    delete[]buf;
}

void svector::at(int i, int& ind, real& val) const {
    ind = buf[i].ind;
    val = buf[i].val;
}

real svector::dot(const svector& v) const {
    real sum = 0.0;
    svector::entry* p = buf;
    svector::entry* q = v.buf;
    while (p < buf + len && q < v.buf + v.len) {
        int diff = p->ind - q->ind;
        if (diff > 0)
            q++;
        else if (diff < 0)
            p++;
        else
            sum += (p++)->val * (q++)->val;
    }
    return sum;
}

real svector::dot(const Array<real>& v) const {
    real sum = 0.0;
    svector::entry* p;
    int sz = v.size();
    for (p = buf; p < buf + len && p->ind < sz; p++)
        sum += p->val* v[p->ind];
    return sum;
}

void svector::update(Array<real>& v) const {
    int y = label;
    svector::entry* p;
    for (p = buf; p < buf + len; p++) {
        while (p->ind >= v.size())
            v.push(0.0);
        v[p->ind] += y* p->val;
    }
}

const int svector::getClass() const {
    return label;
}

const int svector::size() const {
    return len;
}

const float svector::getNorm() {
    if (norm < 0)
        norm = dot(*this);
    return norm;
}
